/*
  wxTriangulator
  Copyright 2008 Boleslaw Kulbabinski

  This program is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  This program is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#include "globals.hpp"
#include "main.hpp"
#include "window.hpp"
#include "algorithms.hpp"

bool Triangulator::OnInit()
{
	TriWindow *window = new TriWindow(wxT("wxTriangulator"), wxPoint(0,0), wxSize(700,500));
	window->Show(true);
	SetTopWindow(window);

	finished = false;
	triangulated = false;

	return true;
}
bool Triangulator::IsEmpty()
{
	return polygon.size() == 0;
}

bool Triangulator::IsFinished()
{
	return finished;
}

bool Triangulator::IsTriangulated()
{
	return triangulated;
}

pair<VP_c_iter, VP_c_iter> Triangulator::GetPolygon()
{
	return make_pair<VP_c_iter, VP_c_iter>(polygon.begin(), polygon.end());
}

pair<VL_c_iter, VL_c_iter> Triangulator::GetTriangulation()
{
	return make_pair<VL_c_iter, VL_c_iter>(triangulation_segments.begin(), triangulation_segments.end());
}

Point Triangulator::AddPoint(long x, long y)
{
	Point other_end;

	if(polygon.empty())
	{
		polygon.push_back(Point(x, y));
		return polygon.back();
	}
	else
	{
		other_end = Point(polygon.back().x, polygon.back().y);
		polygon.push_back(Point(x, y));
		return other_end;
	}
}

Point Triangulator::Finish()
{
	if(polygon.size() < 3)
	{
		throw string("You cannot create a polygon with less than three vertices!");
	}
	else
	{
		finished = true;
		return Point(polygon.back().x, polygon.back().y);
	}
}

void Triangulator::Triangulate()
{
	if(!IsFinished())
	{
		throw string("The polygon is not finished !");
	}

	try
	{
		TriAlgorithm algo;

		algo.Init(make_pair<VP_c_iter, VP_c_iter>(polygon.begin(), polygon.end()));
		algo.Run();

		triangulation_indexes = algo.GetOutcome();

	}
	catch(string error)
	{
		throw error;
	}

	triangulation_segments.resize(triangulation_indexes->size());

	vector<Line>::iterator seg_iter;
	vector<pair<int, int> >::const_iterator ind_iter;

	for(seg_iter = triangulation_segments.begin(),
	    ind_iter = triangulation_indexes->begin();
	    seg_iter != triangulation_segments.end();
	    ++seg_iter, ++ind_iter)
	{
		seg_iter->A.x = polygon[ind_iter->first].x;
		seg_iter->A.y = polygon[ind_iter->first].y;

		seg_iter->B.x = polygon[ind_iter->second].x;
		seg_iter->B.y = polygon[ind_iter->second].y;
	}

	triangulated = true;
}

void Triangulator::Clear()
{
	polygon.clear();

	if(IsTriangulated())
		triangulation_indexes->clear();

	triangulation_segments.clear();
	finished = false;
	triangulated = false;
}

IMPLEMENT_APP(Triangulator)

